<script setup>
  defineOptions({
    name: 'MenuManager',
    inheritAttrs: false,
  });

  import { listMenus, findById, saveMenu, deleteMenu } from '@/api/system/menu';

  import { MenuTypeEnum } from '@/enums/MenuTypeEnum';

  import SvgIcon from '@/components/SvgIcon/index.vue';
  import IconSelect from '@/components/IconSelect/index.vue';

  const queryFormRef = ref(ElForm);
  const menuFormRef = ref(ElForm);

  const loading = ref(false);
  const dialog = reactive({
    title: '',
    visible: false,
  });

  const queryParams = reactive({});
  const menuList = ref([]);

  const menuOptions = ref([
    {
      id: '',
      name: '顶级菜单',
      children: menuList.value,
    },
  ]);

  const formData = reactive({
    parentId: '0',
    visible: 1,
    sort: 1,
    type: MenuTypeEnum.MENU,
    alwaysShow: 0,
    keepAlive: 0,
  });

  const rules = reactive({
    parentId: [{ required: true, message: '请选择顶级菜单', trigger: 'blur' }],
    name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
    type: [{ required: true, message: '请选择菜单类型', trigger: 'blur' }],
    path: [{ required: true, message: '请输入路由路径', trigger: 'blur' }],

    component: [{ required: true, message: '请输入组件路径', trigger: 'blur' }],
    visible: [{ required: true, message: '请输入路由路径', trigger: 'blur' }],
  });

  // 选择表格的行菜单ID
  const selectedRowMenuId = ref();

  const menuCacheData = reactive({
    type: '',
    path: '',
  });

  /**
   * 查询
   */
  function handleQuery() {
    // 重置父组件
    loading.value = true;
    listMenus(queryParams)
      .then(({ data }) => {
        menuList.value = data;
        menuOptions.value = [
          {
            id: '0',
            name: '顶级菜单',
            children: data,
          },
        ];
      })
      .then(() => {
        loading.value = false;
      });
  }

  /** 重置查询 */
  function resetQuery() {
    queryFormRef.value.resetFields();
    handleQuery();
  }

  /**行点击事件 */
  function onRowClick(row) {
    selectedRowMenuId.value = row.id;
  }

  /**
   * 打开表单弹窗
   *
   * @param parentId 父菜单ID
   * @param menuId 菜单ID
   */
  function openDialog(parentId, menuId) {
    dialog.visible = true;
    if (menuId) {
      dialog.title = '编辑菜单';
      findById(menuId).then(({ data }) => {
        Object.assign(formData, data);
        menuCacheData.type = data.type;
        menuCacheData.path = data.path ?? '';
      });
    } else {
      dialog.title = '新增菜单';
      formData.parentId = parentId || '0';
    }
  }

  /** 菜单类型切换事件处理 */
  function onMenuTypeChange() {
    // 如果菜单类型改变，清空路由路径；未改变在切换后还原路由路径
    if (formData.type !== menuCacheData.type) {
      formData.path = '';
    } else {
      formData.path = menuCacheData.path;
    }
  }

  /** 菜单保存提交 */
  function submitForm() {
    menuFormRef.value.validate((isValid) => {
      if (isValid) {
        saveMenu(formData).then((data) => {
          ElMessage.success(data.message || '新增成功');
          closeDialog();
          handleQuery();
        });
      }
    });
  }

  /** 删除菜单 */
  function handleDelete(menuId) {
    if (!menuId) {
      ElMessage.warning('请勾选删除项');
      return false;
    }

    ElMessageBox.confirm('确认删除已选中的数据项?', '警告', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })
      .then(() => {
        deleteMenu(menuId).then(() => {
          ElMessage.success('删除成功');
          handleQuery();
        });
      })
      .catch(() => ElMessage.info('已取消删除'));
  }

  /** 关闭弹窗 */
  function closeDialog() {
    dialog.visible = false;
    resetForm();
  }

  /** 重置表单 */
  function resetForm() {
    menuFormRef.value.resetFields();
    menuFormRef.value.clearValidate();

    formData.id = undefined;
    formData.parentId = '0';
    formData.visible = 1;
    formData.sort = 1;
    formData.perm = undefined;
    formData.component = undefined;
    formData.path = undefined;
    formData.redirect = undefined;
    formData.alwaysShow = undefined;
    formData.keepAlive = undefined;
  }

  onMounted(() => {
    handleQuery();
  });
</script>

<template>
  <div class="app-container">
    <div class="search-container">
      <el-form ref="queryFormRef" :model="queryParams" :inline="true">
        <el-form-item label="关键字" prop="keywords">
          <el-input v-model="queryParams.keywords" placeholder="菜单名称" clearable @keyup.enter="handleQuery" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery"
            ><template #icon><i-ep-search /></template>搜索</el-button
          >
          <el-button @click="resetQuery">
            <template #icon><i-ep-refresh /></template>
            重置</el-button
          >
        </el-form-item>
      </el-form>
    </div>

    <el-card shadow="never" class="table-container">
      <template #header>
        <el-button v-hasPerm="['sys:menu:add']" type="success" @click="openDialog('0')">
          <template #icon><i-ep-plus /></template>
          新增</el-button
        >
      </template>

      <el-table
        v-loading="loading"
        :data="menuList"
        highlight-current-row
        row-key="id"
        :expand-row-keys="['1']"
        @row-click="onRowClick"
        :tree-props="{
          children: 'children',
          hasChildren: 'hasChildren',
        }"
      >
        <el-table-column label="菜单名称" min-width="200">
          <template #default="scope">
            <svg-icon :icon-class="scope.row.icon" />
            {{ scope.row.name }}
          </template>
        </el-table-column>

        <el-table-column label="类型" align="center" width="80">
          <template #default="scope">
            <el-tag v-if="scope.row.type === MenuTypeEnum.CATALOG" type="warning">目录</el-tag>
            <el-tag v-if="scope.row.type === MenuTypeEnum.ROUTE" type="warning">路由</el-tag>
            <el-tag v-if="scope.row.type === MenuTypeEnum.MENU" type="success">菜单</el-tag>
            <el-tag v-if="scope.row.type === MenuTypeEnum.BUTTON" type="danger">按钮</el-tag>
            <el-tag v-if="scope.row.type === MenuTypeEnum.EXTLINK" type="info">外链</el-tag>
          </template>
        </el-table-column>

        <el-table-column label="路由路径" align="left" width="150" prop="path" />

        <el-table-column label="组件路径" align="left" width="250" prop="component" />

        <el-table-column label="权限标识" align="center" width="200" prop="perm" />

        <el-table-column label="状态" align="center" width="80">
          <template #default="scope">
            <el-tag v-if="scope.row.visible === 1" type="success">显示</el-tag>
            <el-tag v-else type="info">隐藏</el-tag>
          </template>
        </el-table-column>

        <el-table-column label="排序" align="center" width="80" prop="sort" />

        <el-table-column fixed="right" align="center" label="操作" width="220">
          <template #default="scope">
            <el-button
              v-if="scope.row.type == 'CATALOG' || scope.row.type == 'MENU'"
              v-hasPerm="['sys:menu:add']"
              type="primary"
              link
              size="small"
              @click.stop="openDialog(scope.row.id)"
            >
              <i-ep-plus />新增
            </el-button>

            <el-button v-hasPerm="['sys:menu:edit']" type="primary" link size="small" @click.stop="openDialog(undefined, scope.row.id)"> <i-ep-edit />编辑 </el-button>
            <el-button v-hasPerm="['sys:menu:delete']" type="primary" link size="small" @click.stop="handleDelete(scope.row.id)"
              ><i-ep-delete />
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <el-dialog v-model="dialog.visible" :title="dialog.title" destroy-on-close append-to-body width="1000px" @close="closeDialog" top="5vh">
      <el-form ref="menuFormRef" :model="formData" :rules="rules" label-width="160px">
        <el-form-item label="父级菜单" prop="parentId">
          <base-tree-select v-model="formData.parentId" placeholder="选择上级菜单" :data="menuOptions" filterable check-strictly :render-after-expand="false" />
        </el-form-item>

        <el-form-item label="菜单名称" prop="name">
          <el-input v-model="formData.name" placeholder="请输入菜单名称" />
        </el-form-item>

        <el-form-item label="菜单类型" prop="type">
          <el-radio-group v-model="formData.type" @change="onMenuTypeChange">
            <el-radio label="CATALOG">目录</el-radio>
            <el-radio label="MENU">菜单</el-radio>
            <el-radio label="BUTTON">按钮</el-radio>
            <el-radio label="EXTLINK">外链</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item v-if="formData.type == 'EXTLINK'" label="外链地址" prop="path">
          <el-input v-model="formData.path" placeholder="请输入外链完整路径" />
        </el-form-item>

        <el-form-item v-if="formData.type == MenuTypeEnum.CATALOG || formData.type == MenuTypeEnum.MENU" label="路由路径" prop="path">
          <el-input v-if="formData.type == MenuTypeEnum.CATALOG" v-model="formData.path" placeholder="system" />
          <el-input v-else v-model="formData.path" placeholder="user" />
        </el-form-item>

        <!-- 组件页面完整路径 -->
        <el-form-item v-if="formData.type == MenuTypeEnum.MENU" label="页面路径" prop="component">
          <el-input v-model="formData.component" placeholder="system/user/index" style="width: 95%">
            <template v-if="formData.type == MenuTypeEnum.MENU" #prepend>src/views/</template>
            <template v-if="formData.type == MenuTypeEnum.MENU" #append>.vue</template>
          </el-input>
        </el-form-item>

        <el-form-item v-if="formData.type !== MenuTypeEnum.BUTTON" prop="visible" label="显示状态">
          <el-radio-group v-model="formData.visible">
            <el-radio :label="1">显示</el-radio>
            <el-radio :label="0">隐藏</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item v-if="formData.type === MenuTypeEnum.CATALOG" label="根目录始终显示">
          <template #label>
            <div>
              根目录始终显示
              <el-tooltip placement="bottom" effect="light">
                <template #content>是：根目录只有一个子路由显示目录 <br />否：根目录只有一个子路由不显示目录，只显示子路由 </template>
                <i-ep-QuestionFilled class="inline-block" />
              </el-tooltip>
            </div>
          </template>

          <el-radio-group v-model="formData.alwaysShow">
            <el-radio :label="1">是</el-radio>
            <el-radio :label="0">否</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item v-if="formData.type === MenuTypeEnum.MENU" label="是否缓存">
          <el-radio-group v-model="formData.keepAlive">
            <el-radio :label="1">是</el-radio>
            <el-radio :label="0">否</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="formData.sort" style="width: 100px" controls-position="right" :min="0" />
        </el-form-item>

        <!-- 权限标识 -->
        <el-form-item v-if="formData.type == MenuTypeEnum.BUTTON" label="权限标识" prop="perm">
          <el-input v-model="formData.perm" placeholder="sys:user:add" />
        </el-form-item>

        <el-form-item v-if="formData.type !== MenuTypeEnum.BUTTON" label="图标" prop="icon">
          <!-- 图标选择器 -->
          <icon-select v-model="formData.icon" />
        </el-form-item>

        <el-form-item v-if="formData.type == MenuTypeEnum.CATALOG" label="跳转路由">
          <el-input v-model="formData.redirect" placeholder="跳转路由" />
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="closeDialog">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
